require("FakeBitOps")
require("FakeCrypto")
print("Testing the FakeBitOps library")

--Hex2Bin Tests
assert(Hex2Bin("")=="","Hex2Bin zero length string failed with "..Hex2Bin(""))
print("Hex2Bin zero length string test succeeded")
assert(Hex2Bin("F")=="1111","Hex2Bin nibble assertion failed with "..Hex2Bin("F"))
print("Hex2Bin nibble assertion succeeded.")
assert(Hex2Bin("FF")=="11111111","Hex2Bin bytelength assertion failed with "..Hex2Bin("FF"))
print("Hex2Bin byte assertion succeeded.")
assert(Hex2Bin("G")=="","Hex2Bin: Malformed string test failed with "..Hex2Bin("G"))
print("Hex2Bin: Malformed string test succeeded")
assert(Hex2Bin("GF")=="1111","Hex2Bin: Mixed string test failed with "..Hex2Bin("GFG"))
print("Hex2Bin: Mixed string test succeeded")

--Bin2Hex Tests
assert(Bin2Hex("")=="","Bin2Hex zero length string failed with "..Bin2Hex(""))
print("Bin2Hex: zero length string test succeeded")
assert(Bin2Hex("1")=="","Bin2Hex less than nibble failed with "..Bin2Hex("1"))
print("Bin2Hex: Less than nibble test succeeded.")
assert(Bin2Hex("1111")=="f","Bin2Hex nibble assertion failed with "..Bin2Hex("1111"))
print("Bin2Hex: nibble assertion succeeded.")
assert(Bin2Hex("11111111")=="ff","Bin2Hex byte assertion failed with "..Bin2Hex("11111111"))
print("Bin2Hex: byte assertion succeeded.")
assert(Bin2Hex("G")=="","Bin2Hex: Malformed string test failed with "..Bin2Hex("G"))
print("Bin2Hex: malformed string test succeeded")
assert(Bin2Hex("G1111G")=="f","Bin2Hex mixed string test failed with "..Bin2Hex("G1111G"))
print("Bin2Hex: Mixed string tests succeeded")

--ZeroPad Tests
assert(ZeroPad("")=="00000000","ZeroPad blank string, null amount, null direciton failed. "..ZeroPad(""))
print("ZeroPad: Blank string, nil amount, nil direction succeeded.")
assert(ZeroPad("0",1)=="0","Padding string of 1 length to 1 failed with "..ZeroPad("0",1))
print("ZeroPad: Padded string to 1 length when it is already 1 length.")
assert(ZeroPad("",1)=="0","Padding 0 length string to 1 failed with "..ZeroPad("",1))
print("ZeroPad: Padding zero length string to 1 succeeded")
assert(ZeroPad("",512)==string.rep("0",512),"ZeroPad: Making a blank 512 string failed with "..ZeroPad("",512))
print("ZeroPad: Making a blank 512 string succeeded.")
assert(ZeroPad("1111",512)==string.rep("0",508).."1111","ZeroPad: Implicit Direction.LEFT test failed with "..ZeroPad("1111",512))
print("ZeroPad: Implicit left padding of 1111 to 512 bits succeeded")
assert(ZeroPad("1111",512,Direction.LEFT)==string.rep("0",508).."1111","ZeroPad: Explicit Direction.LEFT test failed with "..ZeroPad("1111",512))
print("ZeroPad: Explicit left padding of 1111 to 512 bits succeeded")
assert(ZeroPad("1111",512,Direction.RIGHT)=="1111"..string.rep("0",508),"ZeroPad: Explicit Direction.RIGHT test failed with "..ZeroPad("1111",512,Direction.RIGHT))
print("ZeroPad: Explicit right padding of 1111 to 512 bits succeeded")
assert(ZeroPad("11111",512,Direction.LEFT)==string.rep("0",507).."11111","ZeroPad: Odd length string padding test failed with "..ZeroPad("11111",512,Direction.LEFT))
print("ZeroPad: Odd length bitstring padding succeeded")

-- Rotate Tests
assert(Rotate()=="Error, received a nil bitstring","Rotate: Oddly enough, the nil string test failed with "..Rotate())
print("Rotate: nil string returns proper error output. (this is good)")
assert(Rotate("")=="Error, the bitstring must be longer than 1 character.","Rotate: Oddly enough, the blank string test failed with "..Rotate(""))
print("Rotate: Blank string returns proper error output. (this is good)")
assert(Rotate("0")=="Error, the bitstring must be longer than 1 character.","Rotate: Oddly enough, the 1 character rotation didn't return the proper error, instead it returned "..Rotate("0"))
print("Rotate: 1 character rotation error successfully received. (this is good, I was testing for the error)")
assert(Rotate("0001")=="0010","Rotate: Implicit amount, direction and carry failed with "..Rotate("0001"))
print("Rotate: Implicit amount, direction, and carry succeeded")
assert(Rotate("0001",5)=="0010","Rotate: 5 rotation failed with "..Rotate("0001",5))
print("Rotate: 5 rotation succeeded")
assert(Rotate("0001",nil,Direction.RIGHT)=="1000","Rotate: Direction.RIGHT with implicit amount, and carry failed with "..Rotate("0001",nil,Direction.RIGHT))
print("Rotate: Direction.RIGHT rotate with implicit amount, and carry succeeded.")
assert(Rotate("1101",nil,nil,Carry.NO_CARRY)=="1011","Rotate: Implicit amount, direction with Carry.NO_CARRY failed with "..Rotate("1101",nil,nil,Carry.NO_CARRY))
print("Rotate: Implicit amount, direction with Carry.NO_CARRY succeeded")
assert(Rotate("1101",nil,nil,Carry.ZERO_CARRY)=="1010","Rotate: Implicit amount, direction with Carry.ZERO_CARRY failed with "..Rotate("1101",nil,nil,Carry.ZERP_CARRY))
print("Rotate: Implicit amount, direction with Carry.ZERO_CARRY succeeded")
assert(Rotate("0101",nil,nil,Carry.ONE_CARRY)=="1011","Rotate: Implicit amount, direction with Carry.ONE_CARRY failed with "..Rotate("1101",nil,nil,Carry.ONE_CARRY))
print("Rotate: Implicit amount, direction with Carry.ONE_CARRY succeeded")

--MatchBitLengths Tests
--MatchBitLengths(bitstring1,bitstring2,pad_direction)
--And Tests
--And(bitstring1,bitstring2,pad_direction)

--MultiAnd Tests
--MultiAnd(bitstring1,...)

--Or Tests
--Or(bitstring1,bitstring2,pad_direction)

--MultiOr Tests
--MultiOr(bitstring1,...)

--Xor Tests
--Xor(bitstring1,bitstring2,pad_direction)

--MultiXor Tests
--MultiXor(bitstring1,...)

--Not Tests
--Not(bitstring)

--HexZeroPad Tests
--HexZeroPad(hexstring,amount,direction)

--HexRotate Tests
--HexRotate(hexstring,amount,direction,carry)

--HexAnd Tests
--HexAnd(hexstring1,hexstring2,direction)

--MultiHexAnd Tests
--MultiHexAnd(hexstring1,...)

--HexXor Tests
--HexOr(hexstring1,hexstring2,direction)

--MultiHexXor Tests
--MultiHexOr(hexstring1,...)

--HexOr Tests
--HexOr(hexstring1,hexstring2,direction)

--MultiHexOr Tests
--MultiHexOr(hexstring1,...)

--HexNot Tests
--HexNot(hexstring)

--Number2Hex Tests
--Number2Hex(num)

--BinAdd Tests
--BinAdd(bitstring1,bitstring2,truncation_amount,truncation_direction)

--MultiBinAdd Tests
--MultiBinAdd(bitstring1,...)

--Number2Bin Tests
--Number2Bin(num)

--Hex2Number Tests
--Hex2Number(hexstring)

--Bin2Number Tests
--Bin2Number(bitstring)

--String2Hex Tests
--String2Hex(s)

--String2Bin Tests
--String2Bin(s)

--RandomBin Tests
--RandomBin(bitstring_length)

--RandomHex Tests
--RandomHex(hexstring_length)

--BinMultiply
--BinMultiply(bitstring1,bitstring2)

--CouldBeBinString Tests
--CouldBeBinString(bitstring)

--CouldBeHexString Tests
--CouldBeHexString(hexstring)

--Hex2String Tests
--Hex2String(hexstring)

--Bin2String Tests
--Bin2String(bitstring)

--Endian Tests
--Endian(bitstring)

--HexEndian Tests
--HexEndian(hexstring)

--HexAdd Tests
--HexAdd(hexstring1,hexstring2)

--MultiHexAdd Tests
--MultiHexAdd(hexstring1,...)

--HexMultiply Tests
--HexMultiply(hexstring1,hexstring2)

print("Custom operators tests.")
assert("1010" -bxor- "1000" == "0010","bxor isn't working, got "..("1010" -bxor- "1000"))
print("bxor operator is working")
assert("1100" -band- "1000" == "1000","band isn't working, got "..("1100" -band- "1000"))
print("band operator is working")
assert("1100" -bor- "0011" == "1111","bor isn't working, got "..("1100" -bor- "0011"))
print("bor operator is working")
assert("0011" -badd- "0110" == "1001","badd isn't working, got "..("0011" -badd- "0110"))
print("badd operator is working")
assert("0010" -bmul- "0101" == "1010","bmul isn't working, got "..("0010" -bmul- "0101"))
print("bmul operator is working")
assert("0010" -brot- 2 == "1000","brot isn't working, got "..("0010" -brot- 2))
print("brot operator is working")
assert("1111" -bzero- 8 == "00001111","bzero isn't working, got "..("1111" -hzero- 8))
print("bzero operator is working")
assert("F" -hxor- "E" == "1","hxor isn't working, got "..("F" -hxor- "E"))
print("hxor operator is working")
assert("A" -hand- "F" == "a","hand isn't working, got "..("A" -hand- "F"))
print("hand operator is working")
assert("A" -hor- "E" == "e","hor isn't working, got "..("A" -hor- "E"))
print("hor operator is working")
assert("A" -hadd- "6" == "10","hadd isn't working, got "..("A" -hadd- "6"))
print("hadd operator is working")
assert("A" -hmul- "2" == "14","hmul isn't working, got "..("A" -hmul- "2"))
print("hmul operator is working")
assert("5" -hrot- 1 == "a","hrot isn't working, got "..("5" -hrot- 1))
print("hrot operator is working")
assert("F" -hzero- 8 == "0f","hzero isn't working, got "..("F" -hzero- 8))
print("hzero operator is working")
--SHA1 Tests
print("Validating sha1")
assert(sha1.computehash("")=="da39a3ee5e6b4b0d3255bfef95601890afd80709","Test case 1 failed")
print("Test case 1 passed!")
assert(sha1.computehash("The quick brown fox jumps over the lazy dog")=="2fd4e1c67a2d28fced849ee1bb76e7391b93eb12","Test case 2 failed")
print("Test case 2 passed!")
assert(sha1.computehash("The quick brown fox jumps over the lazy cog")=="de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3","Test case 3 failed")
print("Test case 3 passed!")
assert(sha1.computehash("FJNDEG(&*$H#F(4vncsw9r8c4jnhf8")=="fb0673207a79b363c515972c62a7ba29e47db39c","Test case 4 failed")
print("Test case 4 passed!")
assert(sha1.computehash("testing")=="dc724af18fbdd4e59189f5fe768a5f8311527050","Test case 5 failed")
print("Test case 5 passed!")
assert(sha1.computehash("I'm going to make this a really long one, with some U*TFNB#@$7@$98fh4839fhn(*BFH random characters (&$#&(@!&R(&#HCH(&F374hdf somewhere in here*&&#$.")=="20b0d9fee1c05b86a93a94634426e493116307dc","Test case 6 failed")
print("Test case 6 passed!")
assert(sha1.computehash("FakeBitOps rocks.")=="5e6634deb23eb00c09455ba7bc39b3cf27092821","Test case 7 failed")
print("Test case 7 passed!")
print("SHA1 implementation seems correct.")

--HMAC-SHA1 Test
print("Validating hmac-sha1")
assert(hmac(sha1,Hex2String("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),"Hi There") == "b617318655057264e28bc0b6fb378c8ef146be00","Test case 1 didn't pass")
print("Test case 1 passed!")
assert(hmac(sha1,"Jefe","what do ya want for nothing?") == "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79","Test case 2 didn't pass")
print("Test case 2 passed!")
assert(hmac(sha1,Hex2String("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),string.rep(string.char(0xdd),50))=="125d7342b9ac11cd91a39af48aa17b4f63f175d3","Test case 3 didn't pass")
print("Test case 3 passed!")
assert(hmac(sha1,Hex2String("0102030405060708090a0b0c0d0e0f10111213141516171819"),string.rep(string.char(0xcd),50))=="4c9007f4026250c6bc8414f9bf50c86c2d7235da","Test case 4 didn't pass")
print("Test case 4 passed!")
assert(hmac(sha1,Hex2String("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"),"Test With Truncation")=="4c1a03424b55e07fe7f27be1d58bb9324a9a5a04","Test 5a didn't pass")
print("Test case 5a passed!")
assert(string.sub(hmac(sha1,Hex2String("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"),"Test With Truncation"),1,96/4)=="4c1a03424b55e07fe7f27be1","Test 5b didn't pass")
print("Test case 5b passed!") -- 96/4 because 4 hex digits = 1 character
assert(hmac(sha1,string.rep(string.char(0xaa),80),"Test Using Larger Than Block-Size Key - Hash Key First")=="aa4ae5e15272d00e95705637ce8a3b55ed402112","Test 6 didn't pass")
print("Test case 6 passed!")
assert(hmac(sha1,string.rep(string.char(0xaa),80),"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data")=="e8e99d0f45237d786d6bbaa7965c7808bbff1a91","Test 7 didn't pass")
print("Test case 7 passed!")
print("HMAC-SHA1 is fully compliant.")